using System;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;


namespace RunAllTestsInSolutionTask
{
    public class ProjectParser
    {
        private const string TEST_TYPE_GUID =
            "{3AC096D0-A1C2-E12C-1390-A8335801FDAB}";

        public static bool IsTestProject(string projectFileName)
        {
            if (!File.Exists(projectFileName))
                throw new ArgumentException("Project File Doesn't Exists: " + projectFileName);
            var projectXml = XDocument.Load(projectFileName);

            return IsTestProject(projectXml);
        }

        public static string GetOutputDll(string projectFileName, string configuration)
        {
            if (!File.Exists(projectFileName))
                throw new ArgumentException("Project File Doesn't Exists: " + projectFileName);
            if (string.IsNullOrEmpty(configuration))
            { 
                configuration = "debug"; 
            }
            var projectXml = XDocument.Load(projectFileName);
            var outputDll = GetoutputFileName(projectXml,configuration);
            return Path.Combine(Path.GetDirectoryName(projectFileName), outputDll);
            //return Path.GetFullPath(PathRelativeToSln);

        }

        private static bool IsTestProject(XDocument projectXml)
        {
            var ans = from projectType in projectXml.Descendants()
                      where (projectType.Name.LocalName == "ProjectTypeGuids")
                      select projectType;
            foreach (var type in ans)
            {
                if (type.Value.Contains(TEST_TYPE_GUID))
                    return true;

            }
            return false;
        }

        private static string GetoutputFileName(XDocument projectXml, string configuration)
        {
            XElement assemblyName = GetAssemblyFileName(projectXml);
            var propertiesElement = GetConfigurationPropertyGroup(projectXml, configuration);

            XElement outputPath = GetOutputPathElement(propertiesElement);
            return Path.Combine(outputPath.Value, assemblyName.Value) + ".dll";
        }

        private static XElement GetAssemblyFileName(XDocument projectXml)
        {
            var assemblyName = (from projectType in projectXml.Descendants()
                                where (projectType.Name.LocalName == "AssemblyName")
                                select projectType).Single();
            return assemblyName;
        }

        private static XElement GetConfigurationPropertyGroup(XDocument projectXml,string configuration)
        {
            var  propertiesGroups = from x in projectXml.Descendants()
                                   where x.Name.LocalName == "PropertyGroup"
                                   select x;


            var propertyGroup = (from x in propertiesGroups
                                where ( (x.Attribute("Condition") != null) &&
                                  (x.Attribute("Condition").Value.Contains(configuration)) )
                                select x);

            return propertyGroup.Single();
        }

        private static XElement GetOutputPathElement(XElement configurationElemnt)
        {
            var outputPath = (from projectType in configurationElemnt.Descendants()
                              where (projectType.Name.LocalName == "OutputPath")
                              select projectType).First();
            return outputPath;
        }
    }
}
